const Ws = require('ws');
const Http = require('http');
const Path = require('path');
const Chokidar = require('chokidar');

const wsServerConfig = {
	path: '/ws',
	backlog: 1
};

const chokidarWatchPaths = [Path.resolve(__dirname, '../dist')];

const chokidarConfig = {
};

const connsMap = new Map();
const httpServer = Http.createServer();
const wsServer = new Ws.WebSocketServer({...wsServerConfig, server: httpServer});
const chokidarWatcher = Chokidar.watch(chokidarWatchPaths, chokidarConfig);

const setupWatcher = () => {
	console.log(new Date().getTime() + ' chokidar watch paths: ', chokidarWatchPaths);
	let lastTimestamp = 0;
	chokidarWatcher.on('change', () => {
		let deltaTimes = new Date().getTime() - lastTimestamp;
		if(deltaTimes <= 2){
			console.log(new Date().getTime() + ' too quickly change ignore update...');
			return;
		}
		lastTimestamp = new Date().getTime();
		connsMap.forEach((item, id) => {item.send('reload')});
	});

};

const setupWsServer = () => {
	wsServer.on('connection', (conn) => {
		console.log(new Date().getTime() + ' new websocket connection');
		setupWsConn(conn);
	
	});

};

const setupWsConn = (conn) => {
	conn.on('message', (message, isBinary) => {
		console.log(new Date().getTime() + ' receive message: ', isBinary, message.toString());
	});

	conn.on('close', () => {
		console.log(new Date().getTime() + ' conn is closed');
		connsMap.delete(conn.__id);
		console.log(new Date().getTime() + ' now conns: ', connsMap.size);
	});
	
	conn.__id = new Date().getTime();	
	connsMap.set(conn.__id, conn);
	console.log(new Date().getTime() + ' now conns: ', connsMap.size);

};

const startWebSocketServer = async () => {
	setupWatcher();
	setupWsServer();
	await httpServer.listen(8081, '0.0.0.0', ()=>{
		console.log(new Date().getTime() + ' websocket server is listening....');

	});

};

module.exports = startWebSocketServer;